#include "mqtt.h"

#include "DHT11.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "cJSON.h"
#include "esp_log.h"
#include "esp_event.h"
#include "esp_event_loop.h"
#include "mqtt_client.h"
#include "driver/pwm.h"
#include "ws2812.h"

//设备信息
#define DEVICE_TYPE "aithinker"

static const char *TAG = "MQTT Log";

static bool isConnect2Server = false;

typedef struct __User_data
{
	char allData[1024];
	int dataLen;
} User_data;

User_data user_data;

xTaskHandle handleMqtt = NULL;
xTaskHandle mHandlerParseJSON = NULL;	  //任务队列
xTaskHandle PortDataTaskHandle = NULL;	  //任务队列
xQueueHandle ParseJSONQueueHandler_switch = NULL; //解析json数据的队列
xQueueHandle ParseJSONQueueHandler_pwm1 = NULL; //解析json数据的队列
xQueueHandle ParseJSONQueueHandler_pwm2 = NULL; //解析json数据的队列


static char deviceUUID[17];
static uint32_t duites[2];
//mqtt
esp_mqtt_client_handle_t client;
char MqttTopicSub_switch[30], MqttTopicPub_switch[30];
char MqttTopicSub_pwm1[50], MqttTopicPub_pwm1[50];
char MqttTopicSub_pwm2[50], MqttTopicPub_pwm2[50];


/*
 * @Description: 上报数据到服务器
 * @param: null
 * @return:
*/
void post_data_to_clouds(void *parm)
{
	while(1)
	{
		if (!isConnect2Server)
		{
			vTaskDelay(500 / portTICK_PERIOD_MS);
		}
		else
		{
			vTaskDelay(1000/portTICK_PERIOD_MS);
		}
	}
}

/*
 * @Description: 解析下发数据的队列逻辑处理
 * @param: null
 * @return:
*/
void Task_ParseJSON(void *pvParameters)
{
	BaseType_t err;
	printf("[SY] Task_ParseJSON_Message creat ... \n");
	while (1)
	{
		struct __User_data *pMqttMsg;

		printf("[%d] Task_ParseJSON_Message xQueueReceive wait ... \n", esp_get_free_heap_size());
		err = xQueueReceive(ParseJSONQueueHandler_switch, &pMqttMsg, 10);
		if(err==pdTRUE)
		{
			if(strstr(pMqttMsg->allData, "on"))
			{
				esp_mqtt_client_publish(client, MqttTopicPub_switch, "on", 2, 1, 0);
				gpio_set_level(GPIO_NUM_16, 1);
			}
			else if(strstr(pMqttMsg->allData, "off"))
			{
				esp_mqtt_client_publish(client, MqttTopicPub_switch, "off", 3, 1, 0);
				gpio_set_level(GPIO_NUM_16, 0);
			}
		}

		err = xQueueReceive(ParseJSONQueueHandler_pwm1, &pMqttMsg, 10);
		if(err==pdTRUE)
		{
			////首先整体判断是否为一个json格式的数据
			cJSON *pJsonRoot = cJSON_Parse(pMqttMsg->allData);
			ESP_LOGE(TAG, "PWM1_GET DATA %s \n", pMqttMsg->allData);
			//如果是否json格式数据
			if (pJsonRoot == NULL)
			{
				ESP_LOGE(TAG, " pJSON_Item not json ... \n");
				goto __cJSON_Delete1;
			}

			cJSON *pJSON_state = cJSON_GetObjectItem(pJsonRoot, "state");
			cJSON *pJSON_duty = cJSON_GetObjectItem(pJsonRoot, "brightness");

			if(pJSON_state && !pJSON_duty)
			{
				if(strstr(pJSON_state->valuestring, "ON"))
				{
					cJSON *pData = cJSON_CreateObject();
					cJSON_AddStringToObject(pData, "state", "ON");
					cJSON_AddNumberToObject(pData, "brightness", (int)(duites[0]/10000.0*255));
					char *s = cJSON_Print(pData);
					//ESP_LOGI(TAG, "post_data_to_clouds topic end : %s", MqttTopicPub);
					ESP_LOGI(TAG, "post_data_to_clouds payload : %s\n", s);
					esp_mqtt_client_publish(client, MqttTopicPub_pwm1, s, strlen(s), 1, 0);
					cJSON_free((void *)s);
					cJSON_Delete(pData);

					pwm_set_duty(0, duites[0]);
					pwm_start();
				}
				else if(strstr(pJSON_state->valuestring, "OFF"))
				{
					cJSON *pData = cJSON_CreateObject();
					cJSON_AddStringToObject(pData, "state", "OFF");
					char *s = cJSON_Print(pData);
					//ESP_LOGI(TAG, "post_data_to_clouds topic end : %s", MqttTopicPub);
					ESP_LOGI(TAG, "post_data_to_clouds payload : %s\n", s);
					esp_mqtt_client_publish(client, MqttTopicPub_pwm1, s, strlen(s), 1, 0);
					cJSON_free((void *)s);
					cJSON_Delete(pData);

					pwm_set_duty(0, 0);
					pwm_start();
				}
			}
			else if(pJSON_duty)
			{
				if (cJSON_IsNumber(pJSON_duty))
				{
					duites[0] = (int)(pJSON_duty->valueint*10000/255.0);
					pwm_set_duty(0, duites[0]);
					pwm_start();

					cJSON *pData = cJSON_CreateObject();
					cJSON_AddStringToObject(pData, "state", "ON");
					cJSON_AddNumberToObject(pData, "brightness", (int)(duites[0]/10000.0*255));
					char *s = cJSON_Print(pData);
					//ESP_LOGI(TAG, "post_data_to_clouds topic end : %s", MqttTopicPub);
					ESP_LOGI(TAG, "post_data_to_clouds payload : %s", s);
					esp_mqtt_client_publish(client, MqttTopicPub_pwm1, s, strlen(s), 1, 0);
					cJSON_free((void *)s);
					cJSON_Delete(pData);

					ESP_LOGE(TAG, "PWM1_OUT IS %d\n", duites[0]);
				}
				else
				{
					//协议不正确
					ESP_LOGE(TAG, " cJSON_IsNumber  not json ... \n");
					goto __cJSON_Delete1;
				}

			}

			__cJSON_Delete1:
			cJSON_Delete(pJsonRoot);
		}

		err = xQueueReceive(ParseJSONQueueHandler_pwm2, &pMqttMsg, 10);
		if(err==pdTRUE)
		{
			////首先整体判断是否为一个json格式的数据
			cJSON *pJsonRoot = cJSON_Parse(pMqttMsg->allData);
			ESP_LOGE(TAG, "PWM1_GET DATA %s \n", pMqttMsg->allData);
			//如果是否json格式数据
			if (pJsonRoot == NULL)
			{
				ESP_LOGE(TAG, " pJSON_Item not json ... \n");
				goto __cJSON_Delete2;
			}

			cJSON *pJSON_state = cJSON_GetObjectItem(pJsonRoot, "state");
			cJSON *pJSON_duty = cJSON_GetObjectItem(pJsonRoot, "brightness");

			if(pJSON_state && !pJSON_duty)
			{
				if(strstr(pJSON_state->valuestring, "ON"))
				{
					cJSON *pData = cJSON_CreateObject();
					cJSON_AddStringToObject(pData, "state", "ON");
					cJSON_AddNumberToObject(pData, "brightness", (int)(duites[1]/10000.0*255));
					char *s = cJSON_Print(pData);
					//ESP_LOGI(TAG, "post_data_to_clouds topic end : %s", MqttTopicPub);
					ESP_LOGI(TAG, "post_data_to_clouds payload : %s\n", s);
					esp_mqtt_client_publish(client, MqttTopicPub_pwm2, s, strlen(s), 1, 0);
					cJSON_free((void *)s);
					cJSON_Delete(pData);

					pwm_set_duty(1, duites[1]);
					pwm_start();
				}
				else if(strstr(pJSON_state->valuestring, "OFF"))
				{
					cJSON *pData = cJSON_CreateObject();
					cJSON_AddStringToObject(pData, "state", "OFF");
					char *s = cJSON_Print(pData);
					//ESP_LOGI(TAG, "post_data_to_clouds topic end : %s", MqttTopicPub);
					ESP_LOGI(TAG, "post_data_to_clouds payload : %s\n", s);
					esp_mqtt_client_publish(client, MqttTopicPub_pwm2, s, strlen(s), 1, 0);
					cJSON_free((void *)s);
					cJSON_Delete(pData);

					pwm_set_duty(1, 0);
					pwm_start();
				}
			}
			else if(pJSON_duty)
			{
				if (cJSON_IsNumber(pJSON_duty))
				{
					duites[1] = (int)(pJSON_duty->valueint*10000/255.0);
					pwm_set_duty(1, duites[1]);
					pwm_start();

					cJSON *pData = cJSON_CreateObject();
					cJSON_AddStringToObject(pData, "state", "ON");
					cJSON_AddNumberToObject(pData, "brightness", (int)(duites[1]/10000.0*255));
					char *s = cJSON_Print(pData);
					//ESP_LOGI(TAG, "post_data_to_clouds topic end : %s", MqttTopicPub);
					ESP_LOGI(TAG, "post_data_to_clouds payload : %s", s);
					esp_mqtt_client_publish(client, MqttTopicPub_pwm2, s, strlen(s), 1, 0);
					cJSON_free((void *)s);
					cJSON_Delete(pData);

					ESP_LOGE(TAG, "PWM2_OUT IS %d\n", duites[1]);
				}
				else
				{
					//协议不正确
					ESP_LOGE(TAG, " cJSON_IsNumber  not json ... \n");
					goto __cJSON_Delete2;
				}

			}

			__cJSON_Delete2:
			cJSON_Delete(pJsonRoot);
		}
	}
}
/*
 * @Description: MQTT服务器的下发消息回调
 * @param:
 * @return:
*/
esp_err_t MqttCloudsCallBack(esp_mqtt_event_handle_t event)
{
	int msg_id;
	client = event->client;
	switch (event->event_id)
	{
		//连接成功
	case MQTT_EVENT_CONNECTED:
		ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
		msg_id = esp_mqtt_client_subscribe(client, MqttTopicSub_switch, 1);
		ESP_LOGI(TAG, "sent subscribe[%s] successful, msg_id=%d", MqttTopicSub_switch, msg_id);
		msg_id = esp_mqtt_client_subscribe(client, MqttTopicSub_pwm1, 1);
		ESP_LOGI(TAG, "sent subscribe[%s] successful, msg_id=%d", MqttTopicSub_pwm1, msg_id);
		msg_id = esp_mqtt_client_subscribe(client, MqttTopicSub_pwm2, 1);
		ESP_LOGI(TAG, "sent subscribe[%s] successful, msg_id=%d", MqttTopicSub_pwm2, msg_id);
		ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size());
		//post_data_to_clouds();
		isConnect2Server = true;

		if (ParseJSONQueueHandler_switch == NULL)
			ParseJSONQueueHandler_switch = xQueueCreate(5, sizeof(struct esp_mqtt_msg_type *));
		if (ParseJSONQueueHandler_pwm1 == NULL)
			ParseJSONQueueHandler_pwm1 = xQueueCreate(5, sizeof(struct esp_mqtt_msg_type *));
		if (ParseJSONQueueHandler_pwm2 == NULL)
			ParseJSONQueueHandler_pwm2 = xQueueCreate(5, sizeof(struct esp_mqtt_msg_type *));

		WS2812BSend_24bit(0x00, 0xFF, 0x00);
		if(PortDataTaskHandle == NULL)
		{
			xTaskCreate(post_data_to_clouds, "post_data_to_clouds", 1024*4, NULL, 10, &PortDataTaskHandle);
		}

		//开启json解析线程
		if (mHandlerParseJSON == NULL)
		{
			xTaskCreate(Task_ParseJSON, "Task_ParseJSON", 1024*16, NULL, 9, &mHandlerParseJSON);
		}

		break;
		//断开连接回调
	case MQTT_EVENT_DISCONNECTED:
		ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
		WS2812BSend_24bit(0x00, 0x00, 0xFF);
		esp_mqtt_client_start(client);
		isConnect2Server = false;
		break;
		//订阅成功
	case MQTT_EVENT_SUBSCRIBED:
		ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
		break;
		//订阅失败
	case MQTT_EVENT_UNSUBSCRIBED:
		ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
		break;
		//推送发布消息成功
	case MQTT_EVENT_PUBLISHED:
		ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
		break;
		//服务器下发消息到本地成功接收回调
	case MQTT_EVENT_DATA:
	{
		//发送数据到队列
		struct __User_data *pTmper;
		sprintf(user_data.allData, "%s", event->data);
		pTmper = &user_data;
		user_data.dataLen = event->data_len;
		user_data.allData[user_data.dataLen] = '\0';

		//ESP_LOGI(TAG, "msg_id=%s  data [%s] \n", event->topic, user_data.allData);

		if(strstr(event->topic, MqttTopicSub_switch))
			xQueueSend(ParseJSONQueueHandler_switch, (void *)&pTmper, 100);
		else if(strstr(event->topic, MqttTopicSub_pwm1))
			xQueueSend(ParseJSONQueueHandler_pwm1, (void *)&pTmper, 100);
		else if(strstr(event->topic, MqttTopicSub_pwm2))
			xQueueSend(ParseJSONQueueHandler_pwm2, (void *)&pTmper, 100);

		break;
	}
	default:
		break;
	}
	return ESP_OK;
}



/*
 * @Description: MQTT参数连接的配置
 * @param:
 * @return:
*/
void TaskXMqttRecieve(void *p)
{
	//获取mac地址（station模式）
	uint8_t mac[6];
	esp_read_mac(mac, ESP_MAC_WIFI_STA);
	sprintf(deviceUUID, "%02x%02x%02x%02x%02x%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
	//组建MQTT订阅的主题
	//sprintf(MqttTopicSub, "/%s/%s/devSub", DEVICE_TYPE, deviceUUID);
	//组建MQTT推送的主题
	//sprintf(MqttTopicPub, "/%s/%s/devPub", DEVICE_TYPE, deviceUUID);

	sprintf(MqttTopicPub_switch, "office/switch1/state");
	sprintf(MqttTopicSub_switch, "office/switch1/switch");

	sprintf(MqttTopicPub_pwm1, "office/switch1/pwm1/state");
	sprintf(MqttTopicSub_pwm1, "office/switch1/pwm1/pwmcommand");

	sprintf(MqttTopicPub_pwm2, "office/switch1/pwm2/state");
	sprintf(MqttTopicSub_pwm2, "office/switch1/pwm2/pwmcommand");
	printf("ACTUATOR_OPEN\n");

	//连接的配置参数
	esp_mqtt_client_config_t mqtt_cfg = {
		.host = "42.193.109.108", //连接的域名 ，请务必修改为您的
		.port = 1883,			   //端口，请务必修改为您的
		.username = "homeassistant",	   //用户名，请务必修改为您的
		.password = "rieth3aiYie2yohZaghai0Rohv0evaish7weed4Chigetho7phohgaingoh5Ahth",   //密码，请务必修改为您的
		.client_id = deviceUUID,
		.event_handle = MqttCloudsCallBack, //设置回调函数
		.keepalive = 120,					//心跳
		.disable_auto_reconnect = true,	    //开启自动重连
		.disable_clean_session = false,		//开启 清除会话
	};
	client = esp_mqtt_client_init(&mqtt_cfg);
	esp_mqtt_client_start(client);

	vTaskDelete(NULL);
}
